package com.fingard.dsp.bank.directbank.mybank01;

import com.fingard.constant.Format;
import com.fingard.crypto.SignVerifyHelper;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;

import java.io.*;
import java.util.Calendar;
import java.util.Date;

/**
 * Created by Ross on 2017-06-21.
 */
public class MYBank01BatPayRec extends MYBank01Base implements IBatPayRec {

    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        //返回ATS的对象
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req1988.reqHeader);
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req1988.ownAct, "bat");
            String batchNo = String.format("%032d", Long.parseLong(reqHeader.transSeqID));
            String fileName = String.format("h2h_batchTransfer_%s_%s.xls", actItem.merchantId, batchNo);
            //生成xls文件
            String generateFileMsg = generateBatchXlsFile(getBankConfig().getValueAsString("batchTranferTempXlsPath"), getBankConfig().getValueAsString("generateFilePath"), fileName, p_req1988);
            if (!isGenerateSucc) {
                retAts.respCode = "0";
                retAts.respInfo = generateFileMsg;
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = PaymentState.FAIL_Batch;
                retAts.writeRetToATS();
                return retAts;
            }
            //xls文件签名
            String signFileMsg = signXlsFile(getBankConfig().getValueAsString("generateFilePath"), fileName, getBankConfig().getValueAsString("signFilePath"), getBankConfig().getValueAsString("pfxPath_Body"), getBankConfig().getValueAsString("pfxPwd_Body"), getCharset());
            if (!isXlsSignSucc) {
                retAts.respCode = "0";
                retAts.respInfo = signFileMsg;
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = PaymentState.FAIL_Batch;
                retAts.writeRetToATS();
                return retAts;
            }
            FtpSet ftpSet = bankFront.getFtpSet("bat");
            String directDir = "batchPay/" + actItem.merchantId + "/" + p_req1988.payDate.replace("-", "") + "/";
            //上传签名后的xls文件
            String uploadFileMsg = uploadBatchXlsFile(ftpSet, directDir, getBankConfig().getValueAsString("signFilePath") + fileName, fileName);
            if (isUploadSucc) {
                //异步发送批量转账确认
                NoticeBank noticeBank = new NoticeBank(p_req1988, bankFront, fileName);
                noticeBank.setLogFlushTime(this.logFlushTime);
                noticeBank.send();
                retAts.respCode = "0";
                retAts.respInfo = "转账指令已提交银行，请等待银行处理！";
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.PAYING;
                retAts.payInfoCode = PaymentState.PAYING;
                retAts.writeRetToATS();
                return retAts;
            } else {
                retAts.respCode = "0";
                retAts.respInfo = uploadFileMsg;
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = PaymentState.FAIL_Batch;
                retAts.writeRetToATS();
                return retAts;
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            e.printStackTrace();
        }
        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req1988.reqBatchNO;
        }
        retAts.writeRetToATS();
        return retAts;
    }

    private boolean isGenerateSucc = false;

    public String generateBatchXlsFile(String templateFilePath, String generateFilePath, String generateFileName, ReqBatPayRec p_req1988) throws Exception {
        String errorMsg = "";
        try {
            if (templateFilePath.length() > 0 && FileHelper.existFile(templateFilePath)) {
                //1.poi读取批量转账模版文件
                FileInputStream fis = new FileInputStream(templateFilePath);
                HSSFWorkbook workbook = new HSSFWorkbook(fis);
                //得到第一页 sheet
                //页Sheet是从0开始索引的
                HSSFSheet hssfSheet = workbook.getSheetAt(0);
                //2.根据请求报文填充文件
                int currentNum = 0;
                while (p_req1988.readRecord()) {
                    HSSFRow hssfRow = hssfSheet.createRow(currentNum + 1);
                    String purpose = "";
                    //第一列为转账类型：I为行内，D为跨行，Z为支付宝
                    if (p_req1988.readedDetail.recBankCode.toLowerCase().equals(getBankConfig().getValueAsString("alipayBankID"))) {
                        hssfRow.createCell(0).setCellValue("Z");
                        purpose = "支付宝转账";
                    } else if (p_req1988.readedDetail.sameBnk.equals("1")) {
                        hssfRow.createCell(0).setCellValue("I");
                        purpose = "行内转账";
                    } else {
                        hssfRow.createCell(0).setCellValue("D");
                        purpose = "跨行转账";
                        //第六列为收款单位开户行名
                        hssfRow.createCell(5).setCellValue(p_req1988.readedDetail.cnapsName);
                        //第七列为收款单位网点名称
                        hssfRow.createCell(6).setCellValue(p_req1988.readedDetail.cnapsName);
                        //第八列为收款银行行号
                        hssfRow.createCell(7).setCellValue(p_req1988.readedDetail.cnapsCode);
                    }
                    //第二列为付款单位账号
                    hssfRow.createCell(1).setCellValue(p_req1988.readedDetail.payAct);
                    //第三列为付款账户名称
                    hssfRow.createCell(2).setCellValue(p_req1988.readedDetail.payName);
                    //第四列为收款单位账号
                    hssfRow.createCell(3).setCellValue(p_req1988.readedDetail.recAct);
                    //第五列为收款单位名称
                    hssfRow.createCell(4).setCellValue(p_req1988.readedDetail.recName);

                    //第九列为付款金额
                    hssfRow.createCell(8).setCellValue(p_req1988.readedDetail.payAmount);
                    //第十列为付款用途
                    purpose = StringHelper.isNullOrEmpty(p_req1988.readedDetail.purpose) ? purpose : p_req1988.readedDetail.purpose;
                    hssfRow.createCell(9).setCellValue(purpose);
                    //第十一列为到账时间，N为两小时内，H为实时到账
                    hssfRow.createCell(10).setCellValue("H");
                    //第十二列为对账ID
                    hssfRow.createCell(11).setCellValue(p_req1988.readedDetail.askNumber);
                    currentNum++;
                }
                //3.另存文件到指定目录
                String fileFullPath = generateFilePath + generateFileName;
                OutputStream outputStream = new FileOutputStream(fileFullPath);
                workbook.write(outputStream);
                outputStream.close();
                isGenerateSucc = true;
                WriteBankLogLn2("生成批量转账文件成功");
            } else {
                isGenerateSucc = false;
                errorMsg = "未指定模版文件路径或模版文件不存在，请检查！";
            }
        } catch (Exception e) {
            e.printStackTrace();
            isGenerateSucc = false;
            errorMsg = e.getMessage();
        }
        return errorMsg;
    }

    private boolean isXlsSignSucc = false;

    public String signXlsFile(String generateFilePath, String generateFileName, String signFilePath, String pfxPath, String pfxPwd, String encodingName) throws Exception {
        String errorMsg = "";
        FileInputStream fiss = null;
        FileOutputStream fo = null;
        try {
            fiss = new FileInputStream(generateFilePath + generateFileName);
            fo = new FileOutputStream(signFilePath + generateFileName);
            byte[] buff = new byte[fiss.available()];
            int size = fiss.read(buff);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            bos.write(buff, 0, size);
            fiss.read(buff);
            fiss.close();
            byte[] plainData = bos.toByteArray();
            //SignVerifyHelper signVerifyHelper = new SignVerifyHelper();
            SignVerifyHelper.sign(getBankConfig().getValueAsString("pfxConfigPath"), plainData, true, fo);
            isXlsSignSucc = true;
            WriteBankLogLn2("批量转账文件签名成功");
        } catch (Exception e) {
            e.printStackTrace();
            isXlsSignSucc = false;
            errorMsg = e.getMessage();
        } finally {
            if (fiss != null) {
                fiss.close();
            }
            if (fo != null) {
                fo.close();
            }
        }
        return errorMsg;
    }

    private boolean isUploadSucc = false;

    public String uploadBatchXlsFile(FtpSet p_ftpSet, String directDir, String p_XlsFileName, String p_DestFileName) throws Exception {
        SftpPortClient sftp = new SftpPortClient(p_ftpSet);
        FtpReceiver ftpReceiver = sftp.uploadFile(directDir, p_XlsFileName, p_DestFileName);
        String errorMsg = "";
        if (ftpReceiver.isCompleted) {
            isUploadSucc = true;
            WriteBankLogLn2("批量转账文件上传成功");
        } else {
            errorMsg = ftpReceiver.connMsg;
        }
        return errorMsg;
    }

    //1998 状态查询
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req1998.reqHeader);
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req1998.ownAct, "bat");
            Date tmpTimeNow = new Date();
            Date bgnDate = Format.DateTimeFormat.parse(p_req1998.bgnDate);
            long tmpMilSeconds = tmpTimeNow.getTime() - bgnDate.getTime();
            long tmpSeconds = tmpMilSeconds / 1000;
            if (tmpSeconds >= 1800) {
                String dataDir = getDataFileDirectory(p_req1998.getBgnDateTime());
                String fileFullPath = dataDir + File.separator + p_req1998.reqBatchNO;
                String fileContext = FileHelper.readFileText(fileFullPath, getCharset());
                if (fileContext == null || !fileContext.contains(":") || !fileContext.contains("|")) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "转账确认结果未知，无法发起状态查询，请人工核对具体转账交易状态！";
                    retAts.writeBeforeDetail();
                    retAts.writeAfterDetail();
                    return retAts;
                } else if (fileContext.indexOf("S+0000:") != 0) {
                    retAts.respCode = "0";
                    retAts.respInfo = fileContext.split("|")[0].split(":")[1];
                    retAts.reqSeqID = p_req1998.reqBatchNO;
                    retAts.transState = PaymentState.FAIL_Batch;
                    retAts.payInfoCode = PaymentState.FAIL_Batch;
                    retAts.writeBeforeDetail();
                    retAts.writeAfterDetail();
                    return retAts;
                }
                String batchTransNo = fileContext.split("\\|")[1].split(":")[1];

                MYBank01Header bankHeader = new MYBank01Header();
                bankHeader.function = "ant.ebank.transfer.batchpay.query";
                bankHeader.signFields = "queryStartDate,queryEndDate,pageSize,pageIndex,batchTransNo,batchState,companyCardNo";
                bankHeader.signValueField = "sign";

                Date tmpDateNow = new Date();
                bankHeader.reqMsgID = Format.DateTime17Format.format(tmpDateNow);
                bankHeader.reqTime = tmpDateNow;

                XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                writeCommonHeader(xmlWriter, bankHeader);

                xmlWriter.writeStartElement("body");
                xmlWriter.writeElementString("partner", bankFront.operator);

                Calendar tmpCalendarFrom = Calendar.getInstance();
                tmpCalendarFrom.setTime(bgnDate);
                tmpCalendarFrom.set(Calendar.DATE, tmpCalendarFrom.get(Calendar.DATE) - 1);
                xmlWriter.writeElementString("queryStartDate", Format.Date10Format.format(tmpCalendarFrom.getTime()));
                Calendar tmpCalendarTo = Calendar.getInstance();
                tmpCalendarTo.setTime(bgnDate);
                tmpCalendarTo.set(Calendar.DATE, tmpCalendarFrom.get(Calendar.DATE) + 1);
                Calendar currentCal = Calendar.getInstance();
                currentCal.setTime(new Date());
                if (tmpCalendarTo.compareTo(currentCal) > 0) {
                    tmpCalendarTo = currentCal;
                }
                xmlWriter.writeElementString("queryEndDate", Format.Date10Format.format(tmpCalendarTo.getTime()));
                xmlWriter.writeElementString("pageSize", "20");
                xmlWriter.writeElementString("pageIndex", "1");
                xmlWriter.writeElementString("batchTransNo", batchTransNo);
                xmlWriter.writeElementString("batchState", "");
                xmlWriter.writeElementString("companyCardNo", p_req1998.ownAct);
                xmlWriter.writeElementString("sign", "");
                xmlWriter.writeEndElement();
                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), bankHeader);
                XmlTextReader tmpBkReader;
                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/document/response/body/resultInfo/resultStatus");
                        if (tmpRetCode != null && tmpRetCode.equals("S")) {
                            while (tmpBkReader.read("/document/response/body/batchResultList")) {
                                XElement tmpRetNode = tmpBkReader.readedXElement;
                                String tranResultListStr = new String(Base64.decodeBase64(tmpRetNode.innerText), "UTF-8");
                                WriteBankLogLn("银行返回的批量结果信息为：" + tranResultListStr);
                                if (tranResultListStr.length() > 0) {
                                    JSONArray array = JSONArray.fromObject(tranResultListStr);
                                    if (array.size() == 0) {
                                        retAts.respCode = "-1";
                                        retAts.respInfo = "银行未返回结果，请与银行联系核对！";
                                    } else {
                                        for (int i = 0; i < array.size(); i++) {
                                            JSONObject job = array.getJSONObject(i);
                                            String batchState = job.get("batchState") == null ? "" : job.get("batchState").toString();
                                            if (!batchState.equals("FINISH")) {
                                                retAts.respCode = "0";
                                                retAts.respInfo = "银行处理中，暂未返回结果，请等待！";
                                                retAts.reqSeqID = p_req1998.reqBatchNO;
                                                retAts.transState = PaymentState.PAYING;
                                                retAts.payInfoCode = PaymentState.PAYING;
                                                retAts.writeBeforeDetail();
                                            } else {
                                                ///*
                                                String resultMd5 = job.get("resultMd5") == null ? "" : job.get("resultMd5").toString();
                                                String gmtCreate = job.get("gmtCreate") == null ? "" : job.get("gmtCreate").toString();
                                                if (resultMd5.equals("")) {
                                                    retAts.respCode = "0";
                                                    retAts.respInfo = job.get("errorDesc") == null ? "" : job.get("errorDesc").toString();
                                                    retAts.reqSeqID = p_req1998.reqBatchNO;
                                                    retAts.transState = batchState;
                                                    retAts.payInfoCode = batchState;
                                                    retAts.writeBeforeDetail();
                                                } else if (!gmtCreate.equals("")) {
                                                    String directDir = "batchPayResult/" + actItem.merchantId + "/" + gmtCreate.split(" ")[0].replace("-", "") + "/";
                                                    String fileName = String.format("h2h_batchTransferResult_%s_%s.xls", batchTransNo, resultMd5);
                                                    String saveLocalFile = getBankConfig().getValueAsString("downFileBackPath") + fileName;
                                                    FtpSet ftpSet = bankFront.getFtpSet("bat");
                                                    SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
                                                    FtpReceiver ftpReceiver = sftpPortClient.downloadFile(directDir, fileName, saveLocalFile);
                                                    if (!ftpReceiver.isCompleted) {
                                                        retAts.respCode = "-1";
                                                        retAts.respInfo = ftpReceiver.connMsg;
                                                    } else {

                                                        retAts.respCode = "0";
                                                        retAts.respInfo = "";
                                                        retAts.reqSeqID = p_req1998.reqBatchNO;
                                                        retAts.writeBeforeDetail();
                                                        // poi读取excel
                                                        //创建要读入的文件的输入流
                                                        InputStream inp = new FileInputStream(saveLocalFile);
                                                        //根据上述创建的输入流 创建工作簿对象
                                                        HSSFWorkbook workbook = new HSSFWorkbook(inp);
                                                        //得到第一页 sheet
                                                        //页Sheet是从0开始索引的
                                                        HSSFSheet hssfSheet = workbook.getSheetAt(0);
                                                        //利用foreach循环 遍历sheet中的所有行
                                                        int currentRowNum = 0;
                                                        for (Row row : hssfSheet) {
                                                            currentRowNum++;
                                                            if (currentRowNum == 1) {
                                                                continue;
                                                            }
                                                            RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                                                            tmpRetDetail.payAct = row.getCell(1).getStringCellValue();
                                                            tmpRetDetail.payName = row.getCell(2).getStringCellValue();
                                                            tmpRetDetail.recAct = row.getCell(3).getStringCellValue();
                                                            tmpRetDetail.recName = row.getCell(4).getStringCellValue();
                                                            tmpRetDetail.payAmount = row.getCell(8).getStringCellValue();
                                                            tmpRetDetail.usage = row.getCell(9).getStringCellValue();
                                                            tmpRetDetail.postScript = row.getCell(11).getStringCellValue();
                                                            tmpRetDetail.result = row.getCell(12).getStringCellValue();
                                                            tmpRetDetail.payInfoCode = row.getCell(12).getStringCellValue();
                                                            tmpRetDetail.memo = row.getCell(13).getStringCellValue();
                                                            retAts.writeRetDetail(tmpRetDetail);
                                                        }
                                                    }
                                                } else {
                                                    retAts.respCode = "-1";
                                                    retAts.respInfo = "银行返回结果文件摘要值或文件时间无效";
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = tmpBkReader.getFirstText("/document/response/body/resultInfo/resultMsg");
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpStrRet[1];
                }

            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "按银行要求，距离转账提交半小时后方可发起查询！";
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.getMessage();
            e.printStackTrace();
        }
        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req1998.reqBatchNO;
        }
        if (retAts.respCode.equals("-1")) {
            retAts.writeBeforeDetail();
        }
        retAts.writeAfterDetail();
        return retAts;
    }

    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return null;
    }

    //9198
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return null;
    }
}
